package com.nsu.konus.control;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.net.UnknownHostException;

import org.eclipse.core.runtime.Preferences;

/**
 * @author Strot
 */
public class Interlocutor {
	
	public Interlocutor(IKonusParameters parameters) {
		this.parameters = parameters;
	}
	
	public void runDosbox() throws UnknownHostException, IOException, InterruptedException {
		if (sender == null) {
			sender = new CommandsSender(port);
			sender.start();
			runDosboxProcess();
			sender.findDosboxClient();
		}
	}
	
	public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException {
		Preferences pref = new Preferences();
		pref.load(new FileInputStream("konus.conf"));
		
		KonusParameters parameters = new KonusParameters(pref);
		
		Interlocutor i = new Interlocutor(parameters);
		i.startSolver();
	}
	
	private void mountAll() throws IOException, InterruptedException {
		sendString("mount y " + parameters.getRussifierPath());
		sendString("mount c " + parameters.getKonusPath());
		String fortranPath = parameters.getFortranPath();
		if (fortranPath != null && !fortranPath.equals("")) {
			String dir = new File(fortranPath, "BINB").getPath();
			sendString("mount d " + dir);
		}
		sendString("C:");
	}
	
	private void runDosboxProcess() throws IOException {
        Runtime runtime = Runtime.getRuntime();
        runtime.exec(new String[] {"run.bat"});
	}
	
	private void runRussifier() throws IOException, InterruptedException {
		sendString("y:\\rk.com");
	}
	
	private void runSolver() throws IOException, InterruptedException {
		sendString(parameters.getSolverName() + " " + 
				parameters.getParametersDataName());
	}
	
	private void compileFortranFile() throws IOException, InterruptedException {
		//String solverName = parameters.getSolverName();
		//if (solverName == null || solverName.equals(""))
		{
			String fortranSourceName = parameters.getFortranSourceName();
			String name = StringUtils.getFileName(fortranSourceName);
			sendStringWithSleep(20000, "D:\\FL /AH /FPi87 /c " + fortranSourceName);
			sendStringWithSleep(1000, "D:\\LIB " + name + " +" + name + " " + name + ".lst");
			sendStringWithSleep(1000, "file");
			FileWriter writer = new FileWriter(
					new File(parameters.getKonusPath(), name + ".lnk"));
			writer.write(
					"/noe /nod /SE:320 /STACK:6144 /exepack " + name + " +\n" + 
					"( c:\\lnsm-obj\\linsimbg c:\\lnsm-obj\\memread ) +\n" +
					"( c:\\dial-obj\\dialog c:\\dial-obj\\basis +\n" +
					"  c:\\dial-obj\\bndlin c:\\dial-obj\\filer +\n" +
					"  c:\\dial-obj\\graph  c:\\dial-obj\\tablscr ) +\n" +
					"( c:\\solv-obj\\solver1 c:\\solv-obj\\solver2 +\n" +
					"  c:\\solv-obj\\algebr1 c:\\solv-obj\\algebr2 +\n" +
					"  c:\\solv-obj\\invert  c:\\solv-obj\\kvasinew +\n" +
					"  c:\\solv-obj\\lagrange )\n" +
					"  " + name + ".exe\n" +
					"  NUL\n" +
					"  " + name + ".lib dolly c:\\root-obj\\root graphics llibfor7;\n");
			writer.close();
			parameters.setSolverName(name);
			sendStringWithSleep(3000, "D:\\LINK @" + name + ".lnk");
			sendStringWithSleep(1000, "file");
			sendStringWithSleep(60000, "file");
		}
	}
	/*
	private void exitFromProgramm() throws IOException, InterruptedException {
		sender.sendCommand("esc");
	}
	*/
	private void sendString(String s) throws IOException, InterruptedException {
		sender.sendCommand("!" + s);
		sender.sendCommand("enter");
	}
	
	private void createBatFile() throws IOException {
		FileWriter writer = new FileWriter("run.bat");
		writer.write("start " + parameters.getDosboxPath());
		writer.close();
	}
	
	private void execute() throws IOException, InterruptedException {
		createBatFile();
		runDosbox();
	}
	
	private void startSolver() throws UnknownHostException, IOException, InterruptedException{
		execute();
		mountAll();
		runRussifier();
		compileFortranFile();
		runSolver();
		//wait, while solver start work
		Thread.sleep(5000);
		//start solving
		sender.sendCommand("enter");
		//wait, while solver working
		Thread.sleep(parameters.getSolverWorkingTime() * 1000);
		//stop solving
		sendWithSleep(5000, "f10");
		//wait, while solver stopped
		//any key
		
		//delete result file, if it exist
		File resultFile = new File(parameters.getKonusPath(), parameters.getResultFileName());
		if (resultFile.exists()) {
			resultFile.delete();
		}
		
		sendWithSleep(3000, "enter");
		sendWithSleep(1000, "left");
		sendWithSleep(100, "enter");
		sendWithSleep(100, "down");
		sendWithSleep(100, "down");
		sendWithSleep(100, "down");
		sendWithSleep(100, "enter");
		sendString(parameters.getResultFileName());
		Thread.sleep(500);
		sendWithSleep(100, "enter");
		sendWithSleep(100, "enter");
		sendWithSleep(100, "enter");
		sendWithSleep(100, "enter");
		sendWithSleep(100, "enter");
		sendWithSleep(100, "enter");
		sendWithSleep(3000, "f1");
		sendWithSleep(100, "enter");
		sendWithSleep(100, "esc");
		sendWithSleep(100, "right");
		sendWithSleep(100, "right");
		sendWithSleep(1000, "enter");
		sendString("exit");
	}
	
	private void sendWithSleep(int sleepTime, String command) throws IOException, InterruptedException {
		sender.sendCommand(command);
		Thread.sleep(sleepTime);
	}
	
	private void sendStringWithSleep(int sleepTime, String command) throws IOException, InterruptedException {
		sendString(command);
		Thread.sleep(sleepTime);
	}
	
	private int port = 7788;
	
	private CommandsSender sender;
	
	private IKonusParameters parameters;
}
